﻿using System.Windows ;
using System.Windows.Media ;
using System.Windows.Interactivity ;

namespace OpenLightGroup.Common.Behaviors
    {
        public class AttachDataContextBehavior : Behavior<FrameworkElement>
            {
                public AttachDataContextBehavior ( )
                    {

                    }

                #region Properties

                public string ElementName
                {
                    get
                        {
                            return (string)this.GetValue( ElementNameProperty ) ;
                        }
                    set
                        {
                            this.SetValue( ElementNameProperty, value ) ;
                        }
                }

                // Using a DependencyProperty as the backing store for ElementName.  This enables animation, styling, binding, etc...
                public static readonly DependencyProperty ElementNameProperty =
                DependencyProperty.Register( "ElementName", typeof(string), typeof(AttachDataContextBehavior), new PropertyMetadata( null ) ) ;

                public object DataContextType
                {
                    get
                        {
                            return this.GetValue( DataContextTypeProperty ) ;
                        }
                    set
                        {
                            this.SetValue( DataContextTypeProperty, value ) ;
                        }
                }

                // Using a DependencyProperty as the backing store for DataContextType.  This enables animation, styling, binding, etc...
                public static readonly DependencyProperty DataContextTypeProperty =
                DependencyProperty.Register( "DataContextType", typeof(object), typeof(AttachDataContextBehavior), new PropertyMetadata( null ) ) ;

                #endregion

                protected override void OnAttached ( )
                    {
                        base.OnAttached( ) ;

                        FrameworkElement root = Application.Current.RootVisual as FrameworkElement ;
            
                        if ( root != null )
                        {

                            if ( root.Name == this.ElementName && root.DataContext != null 
                                 && root.DataContext.GetType( ) == this.DataContextType.GetType( ) )
                            {
                                this.AssociatedObject.DataContext = root.DataContext ;
                            }
                            else
                            {

                                this.RecursiveSearch( root ) ;

                            }

                        }

                    }

                private void RecursiveSearch ( FrameworkElement parentElement )
                    {
                        if ( this.AssociatedObject.DataContext == null )
                        {
                            FrameworkElement currentElement = VisualTreeHelper.GetChild( parentElement, 0 ) as FrameworkElement ;

                            int childCount = VisualTreeHelper.GetChildrenCount( parentElement ) ;

                            for ( int i = 0 ; i < childCount ; i++ )
                            {
                                FrameworkElement child = VisualTreeHelper.GetChild( currentElement, i ) as FrameworkElement ;

                                var element = child.FindName( this.ElementName ) as FrameworkElement ;

                                if ( element != null && element.DataContext != null && element.DataContext.GetType( ) == this.DataContextType.GetType( ) )
                                {
                                    this.AssociatedObject.DataContext = element.DataContext ;
                                    break ;
                                }
                                else
                                {
                                    this.RecursiveSearch( child ) ;

                                }

                            }

                        }
                    }

            }
    }